#include "squarepanel.h"
#include "stdafx.h"
#include "ExDataPack.h"

using namespace ns_SquarePanel;
const unsigned int iPanelOpenFrames = 4;
const unsigned int iPanelWaitFrames = 6;
const unsigned int iPanelFadeFrames = 20;
const int iShapingPhase	= 0;
const int iRevealPhase	= 1;
const int iEndPhase		= 2;
const int iReadyPhase	= 3;

SquarePanel::SquarePanel(void)
{
	//basic settings
	m_MyState = PanelInvisible;
	m_sOpeningPercent = 0;
	m_sClosingPercent = 0;
	m_PosVisualSize.x = 0;
	m_PosVisualSize.y = 0;
	m_bPanelLocked = true;

	//Create panel bottom rect
	Object* pObj = singObjectFactory::instance().Create( "TriangleStrip2D" );
	pObj->SetLayer( SquarePanelDefaultLayer );
	AddObject( pObj );
	m_IDPanelBottom = singObjectLinker::instance().GetRegID( pObj );

	//Create close button
	PicLocation PL;
	pObj = singObjectFactory::instance().Create( "Button" );
	pObj->SetLayer( SquarePanelDefaultLayer );
	pObj->DirectAddPicLocation( 1, 0, SquarePanelCloseButtonSize.x, 0, SquarePanelCloseButtonSize.y );
	pObj->DirectAddPicLocation( 1, SquarePanelCloseButtonSize.x, SquarePanelCloseButtonSize.x * 2, 0, SquarePanelCloseButtonSize.y );
	pObj->SetSize( SquarePanelCloseButtonSize );
	AddObject( pObj );	
	m_IDPanelCloseButton = singObjectLinker::instance().GetRegID( pObj );
	//init button 0 alpha after attach to panel
	pObj->SetColorAlpha( 0 );

	//set default setting
	SetPosLT( SquarePanelDefaultPos );
	SetSize( SquarePanelDefaultSize );
	PanelObjectPosUpdate();
	SetPanelColour( 0xFFFFFFFF, 0x7700CCFF );

	//Panel start with opening
	OpenPanel();
}

SquarePanel::~SquarePanel(void)
{
}



///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Override from Panel
void SquarePanel::SetPanelColour( const DWORD Colour )
{ 
	//basic setting
	SetColorDWORD( Colour );

	//TODO: Apply setting to all relevant primitives
	TriangleStrip2D* pRect = (TriangleStrip2D*)singObjectLinker::instance().GetObject( m_IDPanelBottom );
	pRect->UpdateColor( Colour );	
}

//multi color panel
void SquarePanel::SetPanelColour( const DWORD ColourLT, const DWORD ColourRest )
{
	//basis color as main color
	SetColorDWORD( ColourRest );

	//Set color to relevant vertex
	POINT PanelPos = GetPosLT();
	//Draw primitive size by its visual size
	POINT PanelSize = m_PosVisualSize;

	TriangleStrip2D* pRect = (TriangleStrip2D*)singObjectLinker::instance().GetObject( m_IDPanelBottom );
	POINT2D Vertexes[4] = 
	{
		{PanelPos.x, PanelPos.y								, ColourLT},
		{PanelPos.x + PanelSize.x, PanelPos.y				, ColourRest},
		{PanelPos.x, PanelPos.y + PanelSize.y				, ColourRest},
		{PanelPos.x + PanelSize.x, PanelPos.y + PanelSize.y	, ColourRest}
	};
	pRect->UpdatePos( Vertexes, 4, true );
}

void SquarePanel::SetPanelPosLT( const POINT &PosLT )
{ 
	//basic setting
	SetPosLT( PosLT ); 

	//TODO: Apply setting to all relevant primitives
	PanelObjectPosUpdate();
}

void SquarePanel::SetPanelSize( const POINT &Size ) 
{ 
	//basic setting
	SetSize( Size ); 

	//TODO: Apply setting to all relevant primitives
	PanelObjectPosUpdate();
}

//Real time logic function
void SquarePanel::RealTimeLogic(void)
{
	//TODO: real time stuffs here
	switch( m_MyState )
	{
	case PanelOpening:
		ProceedOpening();
		break;
	case PanelClosing:
		ProceedClosing();
		break;
	}

	//RTL basis
	//suppose to run all RTL in all involved object
	list<Object*>::iterator itr;
	list<Object*>::iterator itr_end = m_Objects.end();
	for ( itr = m_Objects.begin(); itr != itr_end; ++itr )
	{
		(*itr)->RealTimeLogic();
	}

}

void SquarePanel::MouseClickAt( const POINT &posMouse )
{
	//directly return if panel is locked
	if( m_bPanelLocked )
		return;

	//Panel close process
	const int iCloseScale = 10;
	if( m_posLT.x + m_Size.x - iCloseScale < posMouse.x  && posMouse.x < m_posLT.x + m_Size.x 
		&& m_posLT.y < posMouse.y && posMouse.y < m_posLT.y + iCloseScale )
		ClosePanel();

	return;
}
void SquarePanel::MouseMoveAt( const POINT &posMouse )
{
	//directly return if panel is locked
	if( m_bPanelLocked )
		return;

	//TODO: code here for mouse move process
}
void SquarePanel::KeyDown( const WPARAM &wKey )
{
	//directly return if panel is locked
	if( m_bPanelLocked )
		return;

	//TODO:code here for key down process
}

bool SquarePanel::AddObject( Object* pObject )
{
	if( NULL == pObject )
		return false;

	m_Objects.push_back( pObject );

	//TODO: set up init alterations
	//Add Exdatapack for unpacked objects
	if( !pObject->GetExPack()->FindPack( "ExDataPack" ) )
		pObject->GetExPack()->AddPack( (Expack*)singFactory::instance().Create( "ExDataPack" ) );
	//record object alpha value into exdatapack
	ExDataPack* pDataPack = (ExDataPack*)pObject->GetExPack()->FindPack( "ExDataPack" );
	pDataPack->SetDataGroupByIndex( NS_ExDataPack::EXDATA_ALPHA_RECORD, pObject->GetColorAlpha() );

	return true;
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//unique funs
void SquarePanel::OpenPanel(void)
{
	if( m_MyState == PanelMinimized
		|| m_MyState == PanelInvisible )
	{
		//init open sepence state
		m_iCurrentOpenPhase = iReadyPhase;

		//TODO:Start the Opening
		SwitchToState( PanelOpening );
	}
	
}

void SquarePanel::ClosePanel(void)
{
	if( m_MyState == PanelNormal )
	{
		//init close sepence state
		m_iCurrentClosePhase = iReadyPhase;
		//TODO:Start the Closing
		SwitchToState( PanelClosing );
	}
	
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//private tool funs
void SquarePanel::PanelObjectPosUpdate()
{
	//Update the position of all relevant primitives or objects
	POINT PanelPos = GetPosLT();
	//Draw primitive size by its visual size
	POINT PanelSize = m_PosVisualSize;

	Object* pObj = NULL;
	POINT Pos;

	//Set Panel bottom
	TriangleStrip2D* pRect = (TriangleStrip2D*)singObjectLinker::instance().GetObject( m_IDPanelBottom );
	POINT2D Vertexes[4] = 
	{
		{PanelPos.x, PanelPos.y},
		{PanelPos.x + PanelSize.x, PanelPos.y},
		{PanelPos.x, PanelPos.y + PanelSize.y},
		{PanelPos.x + PanelSize.x, PanelPos.y + PanelSize.y}
	};
	pRect->UpdatePos( Vertexes, 4 );
	//Set panel close button
	pObj = singObjectLinker::instance().GetObject(m_IDPanelCloseButton);
	if( pObj )
	{
		Pos.x = PanelPos.x + m_PosVisualSize.x - SquarePanelCloseButtonSize.x;
		Pos.y = PanelPos.y;
		pObj->SetPosLT( Pos );
		pObj = NULL;
	}
}

void SquarePanel::ProceedOpening()
{
	const POINT ActualSize = GetSize();
	POINT VisualSize = m_PosVisualSize;
	const LONG lExtensionUnitX = ActualSize.x / iPanelOpenFrames;
	const LONG lExtensionUnitY = ActualSize.y / iPanelOpenFrames;

	switch( m_iCurrentOpenPhase )
	{
	case iReadyPhase:
		//init fading percent
		//fade from 0 to 100
		m_sFadingPercent = 0;
		FadeObject( m_sFadingPercent );

		//turn to iShaping phase
		m_iCurrentOpenPhase = iShapingPhase;
		break;

	case iShapingPhase:
		//Open board
		if( VisualSize.x < ActualSize.x )
		{
			//do X and Y axis extension here
			m_PosVisualSize.x += lExtensionUnitX;
			m_PosVisualSize.y += lExtensionUnitY;
			PanelObjectPosUpdate();
		}
		//Open to reveal phase
		else
		{
			//Size secure 
			m_PosVisualSize.x = ActualSize.x;
			m_PosVisualSize.y = ActualSize.y;
			PanelObjectPosUpdate();

			m_iCurrentOpenPhase = iRevealPhase;
		}
		break;

	case iRevealPhase:
		//TODO:: reveal Items
		m_sFadingPercent += unsigned short(100 / iPanelFadeFrames);

		//turn to shaping phase
		if( m_sFadingPercent >= 100 )
		{
			m_sFadingPercent = 100;
            FadeObject( m_sFadingPercent );
			m_iCurrentOpenPhase = iEndPhase;
		}
		else
            FadeObject( m_sFadingPercent );
		break;

	case iEndPhase:
		//Opening finish
		SwitchToState( PanelNormal );
		break;
	}
}

void SquarePanel::ProceedClosing()
{
	const POINT ActualSize = GetSize();
	POINT VisualSize = m_PosVisualSize;
	LONG lExtensionUnitX = ActualSize.x / iPanelOpenFrames;
	LONG lExtensionUnitY = ActualSize.y / iPanelOpenFrames;

	if( 0 == lExtensionUnitX )
		lExtensionUnitX = 1;
	if( 0 == lExtensionUnitY )
		lExtensionUnitY = 1;

	switch( m_iCurrentClosePhase )
	{
	case iReadyPhase:
		//TODO:: Record the object alpha into exdata pack
		RecordAlphaData();

		//init fading percent
		//fade from 100 to 0
		m_sFadingPercent = 100;

		//turn to reveal phase
		m_iCurrentClosePhase = iRevealPhase;
		break;

	case iRevealPhase:
		//TODO:: fade Items 
		m_sFadingPercent -= unsigned short(100 / iPanelFadeFrames);

		//turn to shaping phase
		if( m_sFadingPercent <= iPanelFadeFrames )
		{
			m_iCurrentClosePhase = iShapingPhase;
			m_sFadingPercent = 0;
			FadeObject( m_sFadingPercent );
		}
		else
			FadeObject( m_sFadingPercent );

		break;

	case iShapingPhase:
		if( VisualSize.x > lExtensionUnitX )
		{
			//do X axis extension here
			m_PosVisualSize.x -= lExtensionUnitX;
			PanelObjectPosUpdate();
		}
		else if ( m_sClosingPercent <= iPanelWaitFrames )
		{
			//wait here
			++m_sClosingPercent;
			//Unify visual x 
			m_PosVisualSize.x = 5;
			PanelObjectPosUpdate();
		}
		else if( VisualSize.y > lExtensionUnitY )
		{
			//DO Y axis extension here
			m_PosVisualSize.y -= lExtensionUnitY;
			PanelObjectPosUpdate();
		}
		else
		{
			//Size secure
			m_PosVisualSize.x = 0;
			m_PosVisualSize.y = 0;
			m_sClosingPercent = 0;
			PanelObjectPosUpdate();

			//turn to end phase
			m_iCurrentClosePhase = iEndPhase;
		}
		break;

	case iEndPhase:
		//closing finish
		SwitchToState( PanelInvisible );
		break;
	}
}

void SquarePanel::RecordAlphaData()
{
	ExDataPack* pDataPack = NULL;
	Object* pObj = NULL;

	list<Object*>::iterator itr;
	list<Object*>::iterator itr_end = m_Objects.end();
	for ( itr = m_Objects.begin(); itr != itr_end; ++itr )
	{
		pObj = (*itr);
		if( NULL == pObj )
			continue;

		pDataPack = (ExDataPack*)pObj->GetExPack()->FindPack( "ExDataPack" );
		if( NULL == pDataPack )
			continue;

		pDataPack->SetDataGroupByIndex( NS_ExDataPack::EXDATA_ALPHA_RECORD, pObj->GetColorAlpha() );
	}
}


void SquarePanel::FadeObject( const unsigned short sFadePercent )
{
	ExDataPack* pDataPack = NULL;
	Object* pObj = NULL;
	int iActualAlpha = 0;

	list<Object*>::iterator itr;
	list<Object*>::iterator itr_end = m_Objects.end();
	for ( itr = m_Objects.begin(); itr != itr_end; ++itr )
	{
		//safty concern
		pObj = (*itr);
		if( NULL == pObj )
			continue;
		pDataPack = (ExDataPack*)pObj->GetExPack()->FindPack( "ExDataPack" );
		if( NULL == pDataPack )
			continue;

		//donot fade panel bottom
		if( pObj == singObjectLinker::instance().GetObject( m_IDPanelBottom ) )
			continue;

		iActualAlpha = pDataPack->GetDataGroupByIndex( NS_ExDataPack::EXDATA_ALPHA_RECORD );
		pObj->SetColorAlpha( iActualAlpha * sFadePercent / 100 );
	}
}



void SquarePanel::SwitchToState( ns_SquarePanel::PanelState State )
{
	//TODO: doing state switch here
	m_MyState = State;

	switch( m_MyState )
	{
	case PanelOpening:
		SetVisible( true );
		m_bPanelLocked = true;
		break;
	case PanelClosing:
		m_bPanelLocked = true;
		break;
	case PanelNormal:
		m_bPanelLocked = false;
		break;
	case PanelMinimized:
		m_bPanelLocked = false;
		break;
	case PanelInvisible:
		m_bPanelLocked = true;
		SetVisible( false );
		break;

	default:
		break;
	}	
}
